package com.pai4j.ugc.service;
import com.pai4j.common.enums.MessageTypeEnum;
import com.pai4j.common.enums.messagequeue.MessageBroadChannelEnum;
import com.pai4j.common.service.messagequeue.producer.MessageQueueProducer;
import com.pai4j.common.util.RedisUtil;
import com.pai4j.domain.vo.request.mess.MessageNotifyVO;
import com.pai4j.domain.vo.request.request.ChattingRequestVO;
import com.pai4j.domain.vo.response.UserBaseResponseInfoVO;
import com.pai4j.domain.vo.response.chatting.ChattingListResponseVO;
import com.pai4j.domain.vo.response.mess.ChatMessageResponseVO;
import com.pai4j.ugc.messaegqueue.service.AbstractPersistentMessageService;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.pai4j.common.enums.RedisKeyEnum;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ChatMessageService {

    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private AccountService accountService;
    @Resource
    private AbstractPersistentMessageService persistentMessageService;
    @Autowired
    private MessageQueueProducer<MessageNotifyVO, Long> messageQueueProducer;

    /**
     * 查询用户对话列表
     *
     * @param userId
     * @param lastChatTime
     * @param size
     * @return
     */
    public List<ChattingListResponseVO> listChatting(String userId, Long lastChatTime, Integer size) {

        lastChatTime = lastChatTime == null ? Long.MAX_VALUE : lastChatTime - 1;
        String cacheKey = this.getCacheKey(userId);
        /**
         * 查询最新对话用户列表数据
         */
        Set<String> chattingUsers = redisUtil.zreverseRangeByScore(cacheKey, lastChatTime, 0, size);
        List<String> chattingUserList = new ArrayList<>(chattingUsers);
        List<UserBaseResponseInfoVO> chattingUserInfos = accountService.batchGet(chattingUserList);
        if (CollectionUtils.isEmpty(chattingUserInfos)) {
            return Collections.emptyList();
        }
        /**
         * 查询对话的最近一次时间
         */
        Map<String, Long> lastTimeMap = redisUtil.zscoreTomap(cacheKey, chattingUserList);
        /**
         * 查询未读消息的用户列表，用于标记小红点
         */
        Set<String> unreadUsers = persistentMessageService.getUnreadMessUserSetFromCache(userId);
        /**
         * 查询对话列表最新对话消息内容数据
         */
        Map<String, ChatMessageResponseVO> lastMessageVOMap = persistentMessageService.batchGetUserLastMess(userId, chattingUsers);
        Map<String, String> lastMessageMap = new HashMap<>();
        if (MapUtils.isNotEmpty(lastMessageVOMap)) {
            for (Map.Entry<String, ChatMessageResponseVO> entry : lastMessageVOMap.entrySet()) {
                lastMessageMap.put(entry.getKey(), entry.getValue() != null ? entry.getValue().getPrintMessage() : "有新消息");
            }
        }
        /**
         * 构造用户对话列表
         */
        return chattingUserInfos.stream()
                .filter(Objects::nonNull)
                .map(u -> {
                    return ChattingListResponseVO.builder()
                                .user(u)
                                .unread(unreadUsers.contains(u.getUserId()))
                                .lastChatTime(lastTimeMap.get(u.getUserId()))
                                .lastOfflineMessage(lastMessageMap.get(u.getUserId()))
                                .build();
        }).collect(Collectors.toList());
    }

    /**
     * 对话加入用户对话列表（完全依赖redis缓存）
     *
     * @param chattingRequest
     * @return
     */
    public boolean addChattingList(ChattingRequestVO chattingRequest) {
        /**
         * TODO 后续考虑是否需要持久化，数据一致性保障
         */
        // 基于Sorted Set实现最新对话列表缓存，最新对话时间作为Score用于排序
        String cacheKey = this.getCacheKey(chattingRequest.getAccount());
        Long lastChatTime = chattingRequest.getLastChatTime();
        lastChatTime = lastChatTime == null ? System.currentTimeMillis() : lastChatTime;
        redisUtil.zadd(cacheKey, chattingRequest.getChatAccount(), lastChatTime, RedisKeyEnum.CHAT_ACCOUNT_LIST_CACHE.getExpireTime());
        // 通知客户端对话列表需要刷新
        MessageNotifyVO messageBase = new MessageNotifyVO();
        messageBase.setReceiverId(chattingRequest.getAccount());
        messageBase.setType(MessageTypeEnum.CHATTING_REFRESH.getType());
        messageQueueProducer.broadSend(MessageBroadChannelEnum.QUEUE_CHAT_NOTIFY, messageBase);
        return true;
    }

    /**
     * 从用户最近会话列表移除某个会话（完全依赖redis缓存）
     *
     * @param chattingRequest account: 主账号；chatAccount: 要移除的会话账号
     * @return
     */
    public boolean removeChattingList(ChattingRequestVO chattingRequest) {
        String cacheKey = this.getCacheKey(chattingRequest.getAccount());
        redisUtil.zremove(cacheKey, chattingRequest.getChatAccount());
        // 通知客户端对话列表需要刷新
        MessageNotifyVO messageBase = new MessageNotifyVO();
        messageBase.setReceiverId(chattingRequest.getAccount());
        messageBase.setType(MessageTypeEnum.CHATTING_REFRESH.getType());
        messageQueueProducer.broadSend(MessageBroadChannelEnum.QUEUE_CHAT_NOTIFY, messageBase);
        return true;
    }

    private String getCacheKey(String account) {
        return RedisKeyEnum.CHAT_ACCOUNT_LIST_CACHE.getKey(account);
    }
}
